import au.com.bytecode.opencsv.CSVReader;

import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
import java.util.Date;
import java.util.Calendar;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;


public class ReadUserTimeline {

	
	static int limitedFileSize = 0;

	public static void main(String args[]) {
		try {
			// Setting Parameters
			String CSVFolder = "C:\\Documents and Settings\\workshop\\Desktop\\StackoverflowProject\\StackoverflowProject\\csvData";
			
			String badgeName = "Notable Question";
			int days = 7;
			//Files with file size less than 3 KB will not be processed
			
			folderLevelAggregation(CSVFolder, badgeName, days);

		} catch (Exception e) {
			System.out.println(e);
		}
	}

	private static void folderLevelAggregation(String folderName,
			String badgeName, int days) throws ParseException, IOException {	
		// Search all files in given folder
		File folder = new File(folderName);
		if (!folder.isDirectory()) {
			System.out.println("Please input correct folder name");
			return;
		}

		File[] files = folder.listFiles();
		ArrayList<String> userExperiment = new ArrayList<String>();
		
		/*System.out.println(folder.getAbsoluteFile());
		System.out.println(folder.getAbsoluteFile().getParent());*/
		String outputFileName = folder.getAbsoluteFile()
		.getParent() + "\\" +  badgeName + ".csv";		
		File outputFile = new File(outputFileName);
		boolean fileExists = false;
		if(outputFile.exists()){
			fileExists = true;
		}
		
		PrintStream ps = null;
		//Append records to output file
		FileOutputStream fos = new FileOutputStream(outputFileName, true);
		ps = new PrintStream(fos);
		//If file does not exists, generate the CSV header
		if(!fileExists){
			String csvFileHeader = "UserID,Date,Answered,Questioned,Commented,Revision,Asked,Treatment";
			ps.println(csvFileHeader);
		}
		
		for (File file : files) {
			/*System.out.println(file.getAbsolutePath());*/
			String fileName = file.getAbsolutePath();
			
			
			if (file.isFile()) {
				userExperiment.clear();
				//Check file name
				if(!fileName.contains(".csv")){
					System.out.println("Not CSV file");
					continue;
				}
				
				/*System.out.println(fileName);*/
				String[] tokens = fileName.split("\\\\");				
				/*for(int i = 0; i < tokens.length; ++i){
					System.out.println(tokens[i]);
				}*/
				//The last token should be the file name excluding path directory
				String userID = tokens[tokens.length - 1].replaceAll("\\D+","");
				// Skip if it is not valid user id
				if(userID.equals("")){
					continue;
				}
				
				double fileSize = (double) file.length() / 1024;
				//Skip small files
				if(fileSize < limitedFileSize){
					System.out.println("Skip small file for " + userID);
					continue;
				}				
								
				fileLevelAggregation(fileName, badgeName, days,
						userExperiment);
				if(!userExperiment.isEmpty()){	
					System.out.println("Processing User " + userID);
					Iterator<String> it = userExperiment.iterator();
					while(it.hasNext()){						
						/*System.out.println(userID + "," + it.next());*/						
						ps.println(userID + "," + it.next()+ ", " + badgeName);
					}
					/*System.out.println(user + "," + userExperiment);*/					
				}
				else{					
					System.out.println(String.format(
							"User " + userID + " has no badge of %s", badgeName));
				}
			}
			//If this "file" is directory, recursively call this function
			else if (file.isDirectory()){
				folderLevelAggregation(fileName, badgeName, days);
			}
		}
		//Close output file
		ps.flush();
		ps.close();
		return;
	}

	/**
	 * Prints the activities that are n days before or after the badge is given
	 * @throws IOException 
	 * @throws ParseException 
	 * 
	 */
	private static void fileLevelAggregation(String fileName, String badgeName, int days,
			ArrayList<String> userExperiment) throws ParseException, IOException {
		
		ArrayList<UserActivity> userActivities = readCsvFile(fileName);		
	
		ArrayList<UserActivity> events = new ArrayList<UserActivity> ();
		for(UserActivity ua : userActivities){
			if (ua.badges != null && ua.badges.contains(badgeName)) {
				events.add(ua);					
			}
		}
		if (events != null && events.isEmpty()) {			
			return;
		}
		
		for(UserActivity badgeReceived: events){
			Calendar dateBadgeReceived = badgeReceived.date;
			Calendar fromDate = (Calendar) dateBadgeReceived.clone();
			fromDate.add(Calendar.DATE, -days);
			Calendar toDate = (Calendar) dateBadgeReceived.clone();
			toDate.add(Calendar.DATE, days);

			/*
			 * System.out.println(String.format(
			 * "Activities %d days before and %d days after receiving badge: ",
			 * days, days));
			 * 
			 * System.out.println(String.format("from: %d-%d-%d, to: %d-%d-%d",
			 * fromDate.get(Calendar.DATE), fromDate.get(Calendar.MONTH)+1,
			 * fromDate.get(Calendar.YEAR), toDate.get(Calendar.DATE),
			 * toDate.get(Calendar.MONTH)+1, toDate.get(Calendar.YEAR) ));
			 */

			UserActivity control = new UserActivity(badgeReceived.date);
			UserActivity treatment = new UserActivity(badgeReceived.date);
			int controlCnt = 0;
			int treatmentCnt = 0;
			for (UserActivity ua : userActivities) {
				if (ua.date.after(fromDate) && ua.date.before(badgeReceived.date)) {
					control.add(ua);
					++controlCnt;
					/*System.out.println(ua); */
				} else if (ua.date.after(badgeReceived.date)
						&& ua.date.before(toDate)) {
					/*System.out.println(ua); */
					treatment.add(ua);
					++treatmentCnt;
				} else if (ua.date == badgeReceived.date) {
					treatment.add(ua);
					/*System.out.println(ua); */
				}
			}
			
			/*System.out.println(control.toCSVLine());
			System.out.println(trement.toCSVLine());*/
			//Ensure there is something activities in the given window
			//Otherwise, skip this badge-received event
			if((controlCnt != 0) && (treatmentCnt != 0)){
				userExperiment.add(control.toCSVLine()+ "," + "0");
				userExperiment.add(treatment.toCSVLine()+ "," + "1");
			}			
		}		
		return;
	}

	private static ArrayList<UserActivity> readCsvFile(String fileName)
			throws java.text.ParseException, IOException {
		ArrayList<UserActivity> userActivities = new ArrayList<UserActivity>();	
		CSVReader reader = new CSVReader(new FileReader(fileName));
		List<String[]> csvData = reader.readAll();

		// remove csv headers
		csvData.remove(0);
		
		for (String[] csvLine : csvData) {
			DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
			Date date = format.parse(csvLine[1]);

			Calendar cal = Calendar.getInstance();
			cal.setTime(date);
			UserActivity ua = new UserActivity(cal);
			ua.answered = Integer.parseInt(csvLine[2]);
			ua.questioned = Integer.parseInt(csvLine[3]);
			ua.commented = Integer.parseInt(csvLine[4]);
			ua.revision = Integer.parseInt(csvLine[5]);
			ua.asked = Integer.parseInt(csvLine[6]);
			String badgesCsvStr = csvLine[7];
			if (badgesCsvStr.equals("") || badgesCsvStr.equals("[]")) {
				ua.badges = null;
				/* System.out.println("No Badges!"); */
			} else {
				HashSet<String> badges = new HashSet<String>();
				/* ArrayList<String> badges = new ArrayList<String>(); */
				Collections.addAll(badges, badgesCsvStr.split(","));
				ua.badges = badges;
				/* System.out.println(badges); */
			}
			userActivities.add(ua);
		}
		
		// Close CSV File
		reader.close();
		return userActivities;
	}
}


